﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Data.SqlClient;
using MySql.Data.MySqlClient;
using Region.Utils;

namespace Region
{
    /// <summary> Класс Raspor обеспечивает логику работы с распоряжениями </summary>
    [DBObject(Table = "raspor", PrimaryKeyPole = "RasporID")]
    public class Raspor : DBObject
    {
    const String FileTemplateRTF="Template/Raspor.rtf";
    #region Поля Распоряжения
    [DBColumn(PoleType = EPoleType.RegionDate)]
    public RegionDate Date { get; set; }

    [DBColumn] public Int32 RasporID { get; set; }
    [DBColumn] public Int32 OtdelID { get; set; }
    [DBColumn] public Int32 IspUserID { get; set; }
    [DBColumn] public Int32 KontID { get; set; }
    [DBColumn] public Int32 TP { get; set; }
    [DBColumn] public Int32 NachPodpis { get; set; }
    [DBColumn] public Int32 RucPodpis { get; set; }
    [DBColumn] public Int32 RasporNum { get; set; }
    [DBColumn] public Int32 RasporYear { get; set; }
    [DBColumn] public Int32 Pred { get; set; }
    [DBColumn] public Int32 OsnovID { get; set; }
    [DBColumn] public Int32 Procuror { get; set; }
    [DBColumn] public Int32 Procuror2 { get; set; }
    [DBColumn] public Int32 PredpisFull { get; set; }
    [DBColumn] public Int32 PredpisTime { get; set; }
    [DBColumn] public Int32 NNar { get; set; }
    [DBColumn] public Int32 NumNar { get; set; }
    [DBColumn] public Int32 Predstav { get; set; }
    [DBColumn] public Int32 NStop { get; set; }
    [DBColumn] public Int32 NLic { get; set; }
    [DBColumn] public Int32 SLic { get; set; }
    [DBColumn] public Int32 SudZ1 { get; set; }
    [DBColumn] public Int32 SudZ2 { get; set; }
    [DBColumn] public Int32 Nar1 { get; set; }
    [DBColumn] public Int32 Nar2 { get; set; }
    [DBColumn] public Int32 Nar3 { get; set; }
    [DBColumn] public Int32 SudK1 { get; set; }
    [DBColumn] public Int32 SudK2 { get; set; }
    [DBColumn] public Int32 SudK3 { get; set; }
    [DBColumn] public Int32 Del { get; set; }
    [DBColumn] public Int32 OkvedID { get; set; }
    [DBColumn] public Int64 OrganMask { get; set; }
    //bool
    [DBColumn] public bool StatusVip { get; set; }
    [DBColumn] public bool CheckDoc { get; set; }
    [DBColumn] public bool CheckGo { get; set; }
    [DBColumn] public bool CheckPlan { get; set; }
    [DBColumn] public bool CheckLicen { get; set; }
    //Date

    [DBColumn(PoleType = EPoleType.RegionDate)]
    public RegionDate Start { get; set; }
    [DBColumn(PoleType = EPoleType.RegionDate)]
    public RegionDate End { get; set; }
    [DBColumn(PoleType = EPoleType.RegionDate)]
    public RegionDate FStart { get; set; }
    [DBColumn(PoleType = EPoleType.RegionDate)]
    public RegionDate FEnd { get; set; }
    [DBColumn(PoleType = EPoleType.RegionDate)]
    public RegionDate AktDate { get; set; }
    [DBColumn(PoleType = EPoleType.RegionDate)]
    public RegionDate PredpisDate { get; set; }
    [DBColumn(PoleType = EPoleType.RegionDate)]
    public RegionDate ControlDate { get; set; }    
    //String
    [DBColumn] public String IspInfo { get; set; }
    [DBColumn] public String ExpertsInfo { get; set; }
    [DBColumn] public String TargetInfo { get; set; }
    [DBColumn] public String TaskInfo { get; set; }
    [DBColumn] public String OsnovInfo { get; set; }
    [DBColumn] public String MKontrInfo { get; set; }
    [DBColumn] public String AReglamInfo { get; set; }
    [DBColumn] public String PDocInfo { get; set; }
    [DBColumn] public String RucComment { get; set; }
    [DBColumn] public String NachComment { get; set; }          
    public Otdel Otdel{get{return m_engine.getOtdel(OtdelID);} set{ OtdelID = value.OtdelID;}}
    public User IspUser{get{return m_engine.getUser(IspUserID);} set{ IspUserID = value.UserID;}}
    public User Nach{get{return m_engine.getUser(NachPodpis);} set{ NachPodpis = value.UserID;}}
    public User Ruc{get{return m_engine.getUser(RucPodpis);} set{ RucPodpis = value.UserID;}}
    public Kont Kont{get{return m_engine.getKont(KontID);} set{ KontID = value.KontID;}}
    
    #endregion   
    #region Список проверяющих
    [DBObject(Table = "rasporuser", PrimaryKeyPole = "RasporUserID")]
    public class RasporUser : DBObject
    {
        [DBColumn]
        public Int32 RasporUserID { get; set; }
        [DBColumn]
        public Int32 RasporID { get; set; }
      /// <summary>Идентификатор специалиста</summary>
        [DBColumn]
        public Int32 UserID { get; set; }   
      /// <summary>Время затраченое специалистом на проверку</summary>
        [DBColumn]
        public Int32 WorkTime { get; set; }    
      
      public Raspor Raspor{get{return m_engine.getRaspor(RasporID);} }
      public User User{get{return m_engine.getUser(UserID);} set {UserID = value.UserID;}}        
      /// <summary> Флаг обозначающий удалять запись при сохранении </summary>
      public Boolean Del { get;set;}
      #region Переопределённые методы DBObject
      public override bool save()
      {
        if (Del) return delete(); else return base.save();
      }
      public RasporUser(Engine engine, Int32 RasporUserID, IDictionary<String, Object> Poles = null)
          : base(engine, RasporUserID, Poles)
      {
        m_deleteEnable = true;
      }
      #endregion
    }
    //public class RasporUser { public Int32 RasporUserID; public Int32 UserID; public Int32 WorkTime;}
    private Dictionary<Int32, RasporUser> d_RasporUsers;
    public Dictionary<Int32, RasporUser> RasporUsers { get {isRead(); return new Dictionary<Int32, RasporUser>(d_RasporUsers); } }
    /// <summary>Забать время затраченое на проверку</summary><param name="UserID">ИД проверяющего</param><param name="WorkTime">Время в минутах</param><returns>true - Если удалось изменить время</returns>
    public bool setUserWorkTime(Int32 UserID, Int32 WorkTime)
    {
      if (d_RasporUsers.ContainsKey(UserID))
      {
        d_RasporUsers[UserID].WorkTime = WorkTime;
        return true;
      }
      return false;
    }
    /// <summary>Используется при изменении списка проверяющих</summary>
    public void genIspInfo()
    {
      String S = "";
      foreach (KeyValuePair<Int32, RasporUser> RU in d_RasporUsers)
        if (RU.Value.Del==false)
      {
        User U = m_engine.getUser(RU.Value.UserID);
        if (S != "") S += ", ";
        S += U.Titul2 + " " + U.FullFIO2;
      }
      IspInfo = S;
    }
    /// <summary>Добавить проверяющего в проверку</summary><param name="UserID">ИП проверяющего</param><returns>true - пользователь добавлен</returns>
    public bool AddRasporUser(Int32 UserID)
    {
      if (d_RasporUsers.ContainsKey(UserID)) return false;
      MySqlCommand cmd;          
      var Param = new SQLParam();
      Param["@RasporID"] = RasporID;
      Param["@UserID"] = UserID;
      m_engine.SQLEdit("INSERT INTO rasporuser(RasporID,UserID) VALUES (@RasporID,@UserID)", Param, out cmd);          
      var RU = new RasporUser(m_engine,(Int32)cmd.LastInsertedId);
      RU.UserID = UserID;
      RU.WorkTime = 0;
      d_RasporUsers[RU.UserID] = RU;
      genIspInfo();
      return true;
    }
    /// <summary>Убрать проверяющего в проверку</summary><param name="UserID">ИП проверяющего</param><returns>true - пользователь добавлен</returns>
    public bool DelRasporUser(Int32 UserID)
    {
      if (!d_RasporUsers.ContainsKey(UserID)) return false;
      d_RasporUsers[UserID].Del = true;          
      genIspInfo();
      return true;
    }
    #endregion
    #region Проверяемые объекты
    [DBObject(Table = "rasporobject", PrimaryKeyPole = "RasporObjectID")]
    public class RasporObject : DBObject
    {
        [DBColumn]
        public Int32 RasporObjectID { get { return (Int32)getPole("RasporObjectID"); } }
        [DBColumn]
        public Int32 RasporID { get { return (Int32)getPole("RasporID"); } }
      /// <summary>Идентификатор обекта</summary>
        [DBColumn]
        public Int32 KontObjectID { get { return (Int32)getPole("KontObjectID"); } set { setPole("KontObjectID", value); } }
      /// <summary> Флаг обозначающий удалять запись при сохранении </summary>        
        public Boolean Del { get; set; }
      #region Переопределённые методы DBObject
      public override bool save()
      {
        if (Del) return delete(); else return base.save();
      }
      public RasporObject(Engine engine, Int32 RasporObjectID, IDictionary<String, Object> Poles = null)
          : base(engine, RasporObjectID, Poles)
      {
        m_deleteEnable = true;
      }
      #endregion
    }
    //public class RasporObject { public Int32 KontObjectID;}        
    private Dictionary<Int32, RasporObject> d_RasporObjects;
    public Dictionary<Int32, RasporObject> RasporObjects { get { return new Dictionary<Int32, RasporObject>(d_RasporObjects); } }
    public bool AddRasporObject(Int32 KontObjectID)
    {
      if (d_RasporObjects.ContainsKey(KontObjectID)) return false;
      MySqlCommand cmd;          
      var Param = new SQLParam();
      Param["@RasporID"] = RasporID;
      Param["@KontObjectID"] = KontObjectID;
      m_engine.SQLEdit("INSERT INTO rasporobject(RasporID,KontObjectID) VALUES (@RasporID,@KontObjectID)", Param, out cmd);                    
      var RO = new RasporObject(m_engine,(Int32)cmd.LastInsertedId);
      RO.KontObjectID = KontObjectID;
      d_RasporObjects[RO.KontObjectID] = RO;
      return true;
    }
    public bool DelRasporObject(Int32 KontObjectID)
    {
      if (!d_RasporObjects.ContainsKey(KontObjectID)) return false;
      d_RasporObjects[KontObjectID].Del = true;
      return true;
    }
    #endregion
    #region Нарушения по статьям
    Dictionary<String,Int32> m_LawStNum;
    public Dictionary<String,Int32> LawStNum
    {        
      get
      {
        if (m_Protokols==null) 
        {
          m_LawStNum = new Dictionary<String,Int32>();
          SQLResult R = m_engine.SQLSelect("SELECT  LawStID, RasporLawStNum FROM rasporlawst WHERE RasporID=@RasporID",new SQLParam() { { "@RasporID", RasporID } });
          for(int i=0;i<R.Count;i++)
            m_LawStNum[(String)R[i]["LawStID"]] = (Int32)R[i]["RasporLawStNum"];          
        }
        return m_LawStNum;
      }
    }    
    #endregion
    #region Протоколы      
    Dictionary<Int32,Protokol> m_Protokols;
    public Dictionary<Int32,Protokol> Protokols
    {        
      get
      {
        if (m_Protokols==null) 
        {
          m_Protokols = new Dictionary<Int32, Protokol>();
          SQLResult R = m_engine.SQLSelect("SELECT ProtokolID FROM protokol WHERE RasporID=@RasporID",new SQLParam() { { "@RasporID", RasporID } });
          for(int i=0;R.ContainsKey(i);i++)
          {
            var ProtokolID = (Int32)R[i]["ProtokolID"];
            m_Protokols.Add(ProtokolID,m_engine.getProtokol(ProtokolID));
          }
        }
        return m_Protokols;
      }
    }
    #endregion
    #region Подписи
    /// <summary>Подписать паспоряжение.Сохраняет распоряжение, после установки подписи заного его считывает. У распоряжения должен стоять статус выполнено, пользователь должен иметь право RucPodpis</summary><returns>Если подпись установлена возвращает true</returns>
    public bool AddUserPodpis()
    {
      List<String> ErrorList;
      return AddUserPodpis(out ErrorList);
    }
    /// <summary>Проверить и подписать исполнителем</summary><param name="ErrorList">Список выявленых ошибок распоряжения</param><returns>true - если распоряжение подписано</returns>
    public bool AddUserPodpis(out List<String> ErrorList)
    {
      ErrorList = new List<string>();
      //Проветить права
      if (!poleAccess("Action_StatusVip"))
      {
        ErrorList.Add("У вас нет права на редактирование распоряжений.");
        return false;
      }
      if (!m_engine.CurrentUser.isAccess("Admin") && m_engine.CurrentUser.OtdelID != OtdelID && !m_engine.Otdels[m_engine.CurrentUser.OtdelID].isSubOtdel(OtdelID))
      {
        ErrorList.Add("Нельзя редактировать распоряжение другово отдела.");
        return false;
      }
      //Сохранить перед подписанием
      if (!save())
      {
        ErrorList.Add("Сохранение неудалось.");
        return false;
      }
      ErrorList.AddRange(this.check());
      if (ErrorList.Any()) return false;
      try
      {
        if (m_engine.SQLEdit("UPDATE raspor SET StatusVip=1 WHERE RasporID=@RasporID", new SQLParam() { { "@RasporID", PKValue } }) == 0)
          return false;
      }
      finally { read(); }
      return true;
    }
    /// <summary>Снать подпись исполнителя с распоряжения</summary>
    /// <returns>true -  если удалось снять подпись</returns>
    public bool DelUserPodpis()
    {
      //Проветить права
      if (!poleAccess("Action_StatusVip")) return false;
      try
      {
        if (m_engine.SQLEdit("UPDATE raspor SET StatusVip=0 WHERE RasporID=@RasporID AND RucPodpis=0 AND NachPodpis=0", new SQLParam() { { "@RasporID", PKValue } }) == 0)
            return false;
      }
      finally { read(); }
      return true;
    }
    /// <summary>Поставить подпись руководителя</summary><returns>true -  если удалось поставить подпись</returns>
    public bool AddRucPodpis()
    {
      //Проветить права
      if (!m_engine.isAccess("RucPodpis")) return false;
      //Сохранить перед подписанием
      if (!save()) return false;
      // Вставить подпись в распоряжение, но только если у него стоит статус выполнено
      try
      {
        if (m_engine.SQLEdit("UPDATE raspor SET RucPodpis=@RucPodpis WHERE RasporID=@RasporID AND StatusVip", new SQLParam() { { "@RucPodpis", m_engine.CurrentUser.UserID }, { "@RasporID", PKValue } }) == 0)
          return false;
      }
      finally { read(); }
      return true;
    }
    /// <summary>Убрать подпись руководителя</summary><returns>true - если удалось убрать подпись</returns>
    public bool DelRucPodpis()
    {
      //Проветить права
      if (!m_engine.isAccess("RucPodpis")) return false;
      // Вставить подпись в распоряжение, но только если у него стоит статус выполнено
      try
      {
        if (m_engine.SQLEdit("UPDATE raspor SET RucPodpis=0 WHERE RasporID=@RasporID", new SQLParam() { { "@RasporID", PKValue } }) == 0)
          return false;
      }
      finally { read(); }
      return true;
    }
    /// <summary>Поставить подпись навальника отдела</summary><returns>true - если удалось поставить подпись</returns>
    public bool AddNachPodpis()
    {
      //Проветить права
      if (!m_engine.isAccess("NachPodpis")) return false;
      //Сохранить перед подписанием
      if (!save()) return false;
      // Вставить подпись в распоряжение, но только если у него стоит статус выполнено
      try
      {
        if (m_engine.SQLEdit("UPDATE raspor SET NachPodpis=@NachPodpis WHERE RasporID=@RasporID AND StatusVip AND RucPodpis=0", new SQLParam() { { "@NachPodpis", m_engine.CurrentUser.UserID }, { "@RasporID", PKValue } }) == 0)
          return false;
      }
      finally { read(); }
      return true;
    }
    /// <summary>Снять подпись начальника отдела</summary><returns>true - если удалось убрать подпись</returns>
    public bool DelNachPodpis()
    {
      //Проветить права
      if (!m_engine.isAccess("NachPodpis")) return false;
      // Вставить подпись в распоряжение, но только если у него стоит статус выполнено
      try
      {
        if (m_engine.SQLEdit("UPDATE raspor SET NachPodpis=0 WHERE RasporID=@RasporID AND RucPodpis=0", new SQLParam() { { "@RasporID", PKValue } }) == 0)
          return false;
      }
      finally { read(); }
      return true;
    }
    #endregion
    #region Переопределённые методы DBObject
    public override bool save()
    {
      {//Исполнители
        var NewRasporUsers = new Dictionary<Int32, Raspor.RasporUser>();
        foreach (KeyValuePair<Int32, RasporUser> RU in d_RasporUsers)
        {
          RU.Value.save();
          if (!RU.Value.Del) NewRasporUsers[RU.Value.UserID] = RU.Value;
        }
        d_RasporUsers = NewRasporUsers;
      }
      {//Объекты
        var NewRasporObjects = new Dictionary<Int32, Raspor.RasporObject>();
        foreach (KeyValuePair<Int32, RasporObject> RO in d_RasporObjects)
        {
          RO.Value.save();
          if (!RO.Value.Del) NewRasporObjects[RO.Value.KontObjectID] = RO.Value;
        }
        d_RasporObjects = NewRasporObjects;
      }
      return base.save();
    }
    public override bool isEdit()
    {
      foreach (KeyValuePair<Int32, RasporUser> RU in d_RasporUsers)
        if (RU.Value.isEdit()) 
          return true;
      foreach (KeyValuePair<Int32, RasporObject> RO in d_RasporObjects)
        if (RO.Value.isEdit()) 
          return true;
      return base.isEdit();
    }
    public override bool read(IDictionary<String, Object> Fields)
    {
      d_RasporUsers = new Dictionary<Int32, RasporUser>();
      d_RasporObjects = new Dictionary<Int32, RasporObject>();
      m_Protokols = null;
      if (!base.read(Fields)) return false;
      try
      {
          IDictionary<Int32,Dictionary<String,Object>> ru = null;
          if (Fields.ContainsKey("RasporUser"))
              ru = (IDictionary<Int32, Dictionary<String, Object>>)Fields["RasporObject"];
          else
              ru = m_engine.SQLSelect("SELECT * FROM rasporuser WHERE RasporID=@RasporID", new SQLParam() { { "@RasporID", PKValue } });
          for (int i = 0; i < ru.Count; i++)
        {
            RasporUser RU = new RasporUser(m_engine, (Int32)ru[i]["RasporUserID"], ru[i]);
          d_RasporUsers[RU.UserID] = RU;
        }
      }
      catch { return false; }
      try
      {
          IDictionary<Int32,Dictionary<String,Object>> ro = null;
          if (Fields.ContainsKey("RasporObject"))
              ro = (IDictionary<Int32, Dictionary<String, Object>>)Fields["RasporObject"];
          else
              ro = m_engine.SQLSelect("SELECT * FROM rasporobject WHERE RasporID=@RasporID", new SQLParam() { { "@RasporID", PKValue } });                
        for(int i=0;i<ro.Count;i++)
        {
            var RO = new RasporObject(m_engine, (Int32)ro[i]["RasporObjectID"], ro[i]);          
          d_RasporObjects[RO.KontObjectID] = RO;
        }
      }
      catch { return false; }
      return true;
    }
    /// <summary>Не редактируемые поля. доступны только для администратор</summary>
    static private Dictionary<String, bool> Access_NoEdit = new Dictionary<String, bool>() { { "RasporID", true }, { "RasporNum", true }, { "RasporYear", true }, { "StatusVip", true }, { "RucPodpis", true }, { "NachPodpis", true } };
    /// <summary>Поля закрываемые подписью</summary>
    static private Dictionary<String, bool> Access_BasePoles = new Dictionary<String, bool>() { { "Date", true }, { "CheckDoc", true }, { "CheckGo", true }, { "CheckPlan", true }, { "CheckLicen", true }, { "Pred", true }, { "OsnovID", true }, { "OtdelID", true }, { "IspUserID", true }, { "KontID", true }, { "TP", true }, { "Start", true }, { "End", true }, { "IspInfo", true }, { "ExpertsInfo", true }, { "TargetInfo", true }, { "TaskInfo", true }, { "OsnovInfo", true }, { "MKontrInfo", true }, { "AReglamInfo", true }, { "PDocInfo", true }, { "RucComment", true }, { "NachComment", true }, { "Action_StatusVip", true }, { "Action_RucPodpis", true }, { "Action_NachPodpis", true } };
    public override bool poleCheck(String PoleName, Object Value) { return true; }
    public override bool poleAccess(String PoleName)
    {
        //Не редактируемые поля
        if (Access_NoEdit.ContainsKey(PoleName)) return false;
        // Администратору вообще многое можно           
        if (m_engine.isAccess("Admin")) return true;
        //Основные поля распоряжения
        if (Access_BasePoles.ContainsKey(PoleName))
        {
            //if (m_engine.isAccess("Admin")) return true;
            // Обработка доступа по подписям
            if (m_engine.isAccess("RucPodpis") && PoleName == "Action_RucPodpis") return true;
            if (m_engine.isAccess("RucPodpis") && PoleName == "RucComment") return true;
            if (RucPodpis > 0) return false;
            if (m_engine.isAccess("RucPodpis")) return true;
            if (m_engine.isAccess("NachPodpis") && PoleName == "Action_NachPodpis") return true;
            if (m_engine.isAccess("NachPodpis") && PoleName == "NachComment") return true;
            if (NachPodpis > 0) return false;
            if (m_engine.isAccess("NachPodpis")) return true;
            if (m_engine.isAccess("RasporEdit") && PoleName == "Action_StatusVip") return true;
            if (StatusVip) return false;
        }
        //Разрешить исполнитулю редактировать поля если они не запрещены правилами выше
        if (IspUserID == m_engine.CurrentUser.UserID) return true;
        return false;//Нет явынх править занчит надо запретить            
    }
    #endregion
    /// <summary>Проверить и получить список ошибок в распоряжении</summary><returns>Список ошибок</returns>
    public List<String> check()
    {
      List<String> L = new List<string>();
      if (Date.Year != RasporYear)
        L.Add("Указана не верная дата распоряжения. " + Date.ToShortDateString());
      if (Start.Year < RasporYear && Start.Year > RasporYear + 1)
        L.Add("Указана не верная дата начала проверки. " + Start.ToShortDateString());
      if (End.Year < RasporYear && End.Year > RasporYear + 1)
        L.Add("Указана не верная дата окончания проверки. " + End.ToShortDateString());
      if (Date > Start)
        L.Add("Проверка не может начатся раньше чем выписано распоряжение. ");
      if (Start > End)
        L.Add("Проверка не может закончится раньше её начала. ");
      if (!CheckGo && !CheckDoc)
        L.Add("Проверка должна быть: Документарная,Выездная или Документарно выездная. ");
      if (KontID == 0)
        L.Add("[Пункт 1] Не выбран контрагент. ");
      else
      {
        Kont kont = m_engine.getKont(KontID);
        L.AddRange(kont.checkKont());
        Dictionary<Int32, Kont.KontObject> KO = kont.KontObjects;
        Dictionary<Int32, RasporObject> RO = this.RasporObjects;
        Int32 NumObject = 0;
        foreach (KeyValuePair<Int32, RasporObject> ROI in RO)
          if (KO.ContainsKey(ROI.Value.KontObjectID))
            NumObject += 1;
        if (NumObject==0)
          L.Add("[Пункт 2] Не выбран не один объект.");
      }
      if (Pred == 0)
        L.Add("[Пункт 8] Не выбран предмет проверки. ");
      if (OsnovID == 0)
        L.Add("[Пункт 8] Не выбранно основание проверки. ");
      if (IspUserID == 0)
        L.Add("Не указан исполнитель. ");
      if (!RasporUsers.ContainsKey(IspUserID))
        L.Add("[Пункт 3] Исполнителя нет в списке назначенных лиц на проведение проверки. ");
      if (CheckPlan && KontID > 0)
      {
        Kont kont = m_engine.getKont(KontID);
        SQLResult r = m_engine.SQLSelect("SELECT PlanID FROM plan WHERE KontID=@KontID AND Start=@Start AND RegNum>0", new SQLParam() { { "@KontID", KontID }, { "@Start", Engine.RegionDateToInt(Start) } });
        var PlanList = new List<Int32>();
        for (int i = 0; i < r.Count; i++) PlanList.Add((Int32)r[i]["PlanID"]);
        bool CP = false;
        foreach (Int32 PlanID in PlanList)
        {
          Plan plan = m_engine.getPlan(PlanID);
          switch (TP)
          {
            case 0: if (!(plan.TimeDay > 0 && plan.TimeDay <= 20)) L.Add("Срок проведения проверки не совпадает в плане указано " + plan.TimeDay.ToString() + " дней"); break;
            case 1: if ((plan.TimeH != 50)) L.Add("Срок проведения проверки не совпадает в плане указано " + plan.TimeH.ToString() + " $Plan->TimeH часов"); break;
            case 2: if ((plan.TimeH != 15)) L.Add("Срок проведения проверки не совпадает в плане указано " + plan.TimeH.ToString() + " часов"); break;
          }
          CP = true;
        }
        if (!CP) L.Add("В утверждённом плане нет такого субъекта");
      }
      return L;
    }
    /// <summary>Экспорт в RTF</summary><param name="OutFile">Имя экспортируемого файла</param><returns>true - экспорт удался</returns>
    public bool exportRTF(String OutFile)
    {
        var Poles = new Dictionary<String, Object>();
        if (KontID > 0)
        {
            var kont = new Kont(m_engine, KontID);
            Poles["S1"] = kont.KontName + " ИНН:" + kont.INN + " ОГРН:" + kont.OGRN;
            if (kont.isIP())
            {
            	Poles["S1_1"] = "_____________________________________________________";
            	if (m_engine.PDnAccess)
            	{
            	  IEnumerable<IP> table = (from t in m_engine.bd_IP.IP where t.INN==kont.INN && t.OGRN==kont.OGRN select t);
          if (table.Any())
    		  {
      		    IP ip = table.First();
      		    Poles["S1"] = ip.FIO + " ИНН:" + kont.INN + " ОГРН:" + kont.OGRN;
            	    Poles["S1_1"] = Engine.getAddressString(ip.Post,ip.Region,ip.Raion,ip.Gorod,ip.Naspunkt,ip.Street,ip.Dom,ip.Korpus,ip.Kvart);
    		  }

            	}
            }
            else
            	Poles["S1_1"] = kont.KontULAddress + ((kont.KontFKAddress.Length < 5) ? " фактический адрес:" + kont.KontFKAddress : "");
            Dictionary<Int32, Kont.KontObject> KontObjects = kont.KontObjects;
            Dictionary<Int32, String> Raions = m_engine.Raions;
            foreach (KeyValuePair<Int32, RasporObject> RO in RasporObjects)
            {
                Kont.KontObject KO = KontObjects[RO.Value.KontObjectID];
                Poles["S1_1"] += ", " + KO.KontObjectName + ": " + Engine.getAddressString(KO.KontObjectPostIndex, KO.KontObjectRegion, Raions[KO.KontObjectRaionID], KO.KontObjectGorod, KO.KontObjectNaspunkt, KO.KontObjectStreet, KO.KontObjectDom, KO.KontObjectKorpus, KO.KontObjectKvart);
            }
        }
        Poles["S2"] = IspInfo;
        //Привлечь экспертов
        Poles["S3"] = ExpertsInfo;
        //Цель проведения проврки
        Poles["S4_1"] = TargetInfo;
        //Задачи проведения проверки
        Poles["S4_2"] = TaskInfo;
        if (Pred == 1) Poles["S5_1"] = @"\u8730  "; else Poles["S5_1"] = ((char)127) + " ";
        if (Pred == 2) Poles["S5_2"] = @"\u8730  "; else Poles["S5_2"] = ((char)127) + " ";
        if (Pred == 3) Poles["S5_3"] = @"\u8730  "; else Poles["S5_3"] = ((char)127) + " ";
        if (Pred == 4) Poles["S5_4"] = @"\u8730  "; else Poles["S5_4"] = " ";
        if (Pred == 41) { Poles["S5_41"] = @"\u9679  "; Poles["S5_4"] = @"\u8730  "; } else Poles["S5_41"] = @"\u0032  ";
        if (Pred == 42) { Poles["S5_42"] = @"\u9679  "; Poles["S5_4"] = @"\u8730  "; } else Poles["S5_42"] = @"\u0032  ";
        if (Pred == 43) { Poles["S5_43"] = @"\u9679  "; Poles["S5_4"] = @"\u8730  "; } else Poles["S5_43"] = @"\u0032  ";
        if (Pred == 44) { Poles["S5_44"] = @"\u9679  "; Poles["S5_4"] = @"\u8730  "; } else Poles["S5_44"] = @"\u0032  ";
        //вид и форма проверки
        switch (TP)
        {
            case 0: Poles["S6"] = "не более 20 рабочих дней"; break;
            case 1: Poles["S6"] = "50 часов"; break;
            case 2: Poles["S6"] = "15 часов"; break;
        }
        Poles["S7_1"] = "";
        Poles["S7_1"] += (CheckPlan)?" плановая ":" внеплановая ";
        if (CheckLicen) Poles["S7_1"] += " по лицензионному контролю ";
        if (CheckDoc) Poles["S7_1"] += " документарная ";
        if (CheckGo) Poles["S7_1"] += " выездная ";
        Poles["S8_1"] = Start.ToShortDateString() + " г.";
        Poles["S8_2"] = End.ToShortDateString() + " г.";
        Poles["S10"] = m_engine.OsnovFull[OsnovID] + "; " + OsnovInfo;
        //Дата
        Poles["C_Date"] = Date.ToShortDateString();
        //Номер
        Poles["C_Num"] = RasporNum.ToString();
        //9. В процессе проверки провести следующие мероприятия по контролю, необходимые для достижения целей и задач проведения проверки:
        Poles["S11"] = MKontrInfo;
        Poles["S11_Date"] = " с " + Start.ToShortDateString() + " г. по " + End.ToShortDateString() + " г.";

        //10. Перечень административных регламентов проведения мероприятий по контролю (при их наличии):
        Poles["S12"] = AReglamInfo;
        //11. Перечень документов, представление которых юридическим лицом, индивидуальным предпринимателем необходимо для достижения целей и задач проведения проверки:
        Poles["S14"] = PDocInfo;
        if (RucPodpis > 0)
        {
            Poles["FIO"] = m_engine.getUser(RucPodpis).FullFIO;
            Poles["Dolgn"] = m_engine.getUser(RucPodpis).Titul;
        }
        else
        {
            Poles["FIO"] = "";
            Poles["Dolgn"] = "";
        }
        Poles["Ispoln"] = m_engine.getUser(IspUserID).FIO + ", " + m_engine.getUser(IspUserID).Titul + @" \line " + m_engine.getUser(IspUserID).Telefon;
        //Вставка подписи  
        Poles["Podpis"] = RegionRes.ResourceManager.GetObject("User" + RucPodpis);
        if (Poles["Podpis"] == null) Poles["Podpis"] = " \n ";
        
        return Utils.Export.export("rtf",File.ReadAllBytes(FileTemplateRTF), OutFile, Poles, null);
    }
    public Raspor(Engine engine, Int32 RasporID, IDictionary<String, Object> Poles = null)
        : base(engine, RasporID, Poles)
    {      
      d_RasporUsers = new Dictionary<Int32, RasporUser>();
      d_RasporObjects = new Dictionary<Int32, RasporObject>();      
    }

  }
  /// <summary> Класс RasporList обеспечивает работу со списками распоряжиний </summary>
  public struct RasporListLine
  {
    public Int32 RasporID;
    public Int32 RasporNum;
    public DateTime Date;
    public Int32 OnlineID;
    public String KontName;
    public String IspFIO;
    public bool Podpis;
    public bool StatusVip;
    public String RucComment;
    public String getLinkText()
    {
        return RasporNum.ToString() + " от " + Date.ToShortDateString() + " " + KontName;
    }
  }
  public class RasporList:DBList<RasporListLine>
  { 
    void _ExportListXMLX_Task(Object Param, TaskManager.Task task) {ExportListXMLX((String)Param,task);}
    public TaskManager.Task ExportListXMLX_Task(String FileName){ return m_engine.taskManager.addTask(_ExportListXMLX_Task,"Формирование реестра распоряжеиний", FileName);}
    public bool ExportListXMLX(String FileName, TaskManager.Task task = null)
    {
        var sw = new System.Diagnostics.Stopwatch();
        sw.Start();
      var EL = new List<Dictionary<String,Object>>();
      var Raions = m_engine.Raions;
      var KT = m_engine.KontType;
      var Osnov = m_engine.Osnov;
      var Otdels = m_engine.Otdels;
      setWhere("IgnorePage", true);
      //Кеширование распоряжений
      m_engine.preLoadRaspor(this);

      var old_lines = new List<RasporListLine>(m_lines);
      if (task!=null) task.TaskName = "Чтение из базы данных";
      Filter();
      var YNN_List = new Dictionary<Int32,String>(){{0,"Нет"},{1,"Да"},{-1,"[Не указан]"}};
      var NNar_List = new Dictionary<Int32,String>(){{0,"Выявлены"},{1,"Не выявлены"},{-1,"[Не указано]"}};
      if (task!=null)
      {
      	task.TaskName = "Формирование реестра распоряжеиний";
      	task.TaskMax = m_lines.Count;
      	task.TaskValue = 0;
      }
      var lawst =  m_engine.LawSt;
      var lawstpoles =  lawst.Keys.ToArray();
      var OkvedList = m_engine.Okved;
      foreach(RasporListLine line in m_lines)
      {
        var ExportLine = new Dictionary<String,Object>();
        var Raspor = m_engine.getRaspor(line.RasporID);        
        for(Int32 i=0;i<lawstpoles.Length;i++)
        {
          ExportLine["%"+lawstpoles[i]+"%"] = 0;
          ExportLine["%"+lawst[lawstpoles[i]].LawID+"%"] = 0;
        }
        foreach(var LawSt in Raspor.LawStNum)
        {
          ExportLine["%"+LawSt.Key+"%"] = LawSt.Value;
          ExportLine["%"+lawst[LawSt.Key].LawID+"%"] = (int)ExportLine["%"+lawst[LawSt.Key].LawID+"%"] + LawSt.Value;
        }
        ExportLine["%Okved%"] = OkvedList[Raspor.OkvedID].OkvedName;
        ExportLine["%RasporNum%"] = Raspor.RasporNum;
        ExportLine["%Date%"] = Raspor.Date;
        ExportLine["%CheckDoc%"] = Raspor.CheckDoc?"Документарная":"";
        ExportLine["%CheckGo%"] = Raspor.CheckGo?"Выездная":"";
        ExportLine["%CheckPlan%"] = Raspor.CheckPlan?"Плановая":"Внеплановая";
        ExportLine["%CheckLicen%"] = Raspor.CheckLicen?"По лицензионному контролю":"";
        if (Raspor.KontID>0)
        {
          var Kont = m_engine.getKont(Raspor.KontID);
          ExportLine["%KontName%"] = Kont.KontName;
          ExportLine["%INN%"] = Kont.INN;
          ExportLine["%OGRN%"] = Kont.OGRN;
          ExportLine["%KontType%"] = KT[Kont.KontTypeID];
          ExportLine["%KontULAddress%"] = Kont.KontULAddress;
          ExportLine["%KontFKAddress%"] = Kont.KontFKAddress;
          ExportLine["%KontGosReg%"] = Kont.KontGosReg;
          ExportLine["%ObjectList%"] = "";
          var KontObjecs = Kont.KontObjects;
          foreach(var RasporObject in Raspor.RasporObjects)
            if (KontObjecs.ContainsKey(RasporObject.Value.KontObjectID))
          {                            
            var KontObject = KontObjecs[RasporObject.Value.KontObjectID];
            ExportLine["%ObjectList%"] +=  KontObject.KontObjectName + ", " + Engine.getAddressString(KontObject.KontObjectPostIndex,KontObject.KontObjectRegion,Raions[KontObject.KontObjectRaionID],KontObject.KontObjectGorod,KontObject.KontObjectNaspunkt,KontObject.KontObjectStreet,KontObject.KontObjectDom,KontObject.KontObjectKorpus,KontObject.KontObjectKvart)+"("+m_engine.KontDirect[KontObject.KontObjectDirect]+")"+";\n";
          }   
        }
        ExportLine["%IspInfo%"] = Raspor.IspInfo;
        ExportLine["%ExpertsInfo%"] = Raspor.ExpertsInfo;
        ExportLine["%TargetInfo%"] = Raspor.TargetInfo;
        ExportLine["%TaskInfo%"] = Raspor.TaskInfo;
        
        ExportLine["%TP%"] = Raspor.TP;
        ExportLine["%Start%"] = Raspor.Start;
        ExportLine["%End%"] = Raspor.End;
        ExportLine["%Osnov%"] = Osnov[Raspor.OsnovID];
        ExportLine["%OsnovInfo%"] = Raspor.OsnovInfo;
        ExportLine["%MKontrInfo%"] = Raspor.MKontrInfo;
        ExportLine["%AReglamInfo%"] = Raspor.AReglamInfo;
        ExportLine["%PDocInfo%"] = Raspor.PDocInfo;
        ExportLine["%Status%"] = Raspor.StatusVip?"Выполнено":"Черновик";            
        ExportLine["%IspUser%"] = m_engine.getUser(Raspor.IspUserID).FIO;
        ExportLine["%Otdel%"] = Otdels[Raspor.OtdelID].OtdelName;
        ExportLine["%NachPodpis%"] = Raspor.NachPodpis==0?"":m_engine.getUser(Raspor.NachPodpis).FIO;
        ExportLine["%RucPodpis%"] = Raspor.RucPodpis==0?"":m_engine.getUser(Raspor.RucPodpis).FIO;
        ExportLine["%Procuror%"] = Raspor.Procuror;
        ExportLine["%Del%"] = Raspor.Del;
        //результаты
        ExportLine["%AktDate%"] = Raspor.AktDate;
        ExportLine["%FStart%"] = Raspor.FStart;
        ExportLine["%FEnd%"] = Raspor.FEnd;
        ExportLine["%PredpisDate%"] = Raspor.PredpisDate;
        ExportLine["%ControlDate%"] = Raspor.ControlDate;
        ExportLine["%PredpisFull%"] = YNN_List[Raspor.PredpisFull];
        ExportLine["%PredpisTime%"] = YNN_List[Raspor.PredpisTime];
        ExportLine["%NNar%"] = NNar_List[Raspor.NNar];
        
        ExportLine["%NumNar%"] = Raspor.NumNar;
        ExportLine["%Predstav%"] = YNN_List[Raspor.Predstav];
        ExportLine["%NStop%"] = YNN_List[Raspor.NStop];
        Dictionary<Int32,Protokol> Protokols = Raspor.Protokols;
        Int32 SumP=0, SumP2=0;
        String ListProtokol = "";
        var Article = m_engine.Article;
        foreach(var P in Protokols)
        {
          String Info ="";
          if (P.Value.MeasureID==1) Info += " штраф "+P.Value.SumP.ToString();
          if (P.Value.MeasureID==2) Info += " предупреждение ";
          if (P.Value.MeasureID==6) Info += " прекращено ";
          if (P.Value.MeasureID==0) Info += " не расмотренно ";
          if (P.Value.MeasureID==4 && P.Value.MeasureSudID==0) Info += " не расмотренно судом ";
          if (P.Value.MeasureSudID==4 || P.Value.MeasureSudID==5) Info += " суд:штраф  "+P.Value.SumP.ToString();
          if (P.Value.MeasureSudID==1 ) Info += " суд:предупреждение  ";
          if (P.Value.MeasureSudID==6 || P.Value.MeasureSudID==7) Info += " суд:Приостановление деятельности  ";
          ListProtokol += "№"+P.Value.ProtokolNum + " от " + P.Value.ProtokolReg.ToShortDateString()+ " " + Article[P.Value.ArticleID]+Info+";\n";
          SumP+=P.Value.SumP;
          SumP2+=P.Value.SumP2;
        }
        Int32 RasporUserTime=0;
        String RasporUserTimeList="";
        foreach(var u in Raspor.RasporUsers)
        {
        	RasporUserTimeList += u.Value.User.FIO + " "+  (u.Value.WorkTime/60.0).ToString()+" ч.;\n";
        	RasporUserTime+= u.Value.WorkTime;
        }
        ExportLine["%RasporUserTime%"] = RasporUserTime/60;
        ExportLine["%RasporUserTimeList%"] = RasporUserTimeList;
        ExportLine["%NumProtokol%"] = Protokols.Count;
        ExportLine["%ListProtokol%"] = ListProtokol;
        ExportLine["%ProtokolSumP%"] = SumP;
        ExportLine["%ProtokolSumP2%"] = SumP2;
        ExportLine["%NLic%"] = YNN_List[Raspor.NLic];
        ExportLine["%SLic%"] = YNN_List[Raspor.SLic];
        ExportLine["%SudZ1%"] = Raspor.SudZ1;
        ExportLine["%SudZ2%"] = Raspor.SudZ2;
        ExportLine["%Nar1%"] = YNN_List[Raspor.Nar1];
        ExportLine["%Nar2%"] = YNN_List[Raspor.Nar2];
        ExportLine["%Nar3%"] = YNN_List[Raspor.Nar3];
        ExportLine["%SudK1%"] = Raspor.SudK1;
        ExportLine["%SudK2%"] = Raspor.SudK2;
        ExportLine["%SudK3%"] = Raspor.SudK3;
        EL.Add(ExportLine);
        if (task!=null) task.TaskValue += 1;
      }      
      setWhere("IgnorePage", false);
      m_lines=old_lines;
      sw.Stop();
      var Template = m_engine.getRegionFile("ReestrRaspor","xlsx");
      var Poles = new Dictionary<String,Object>();
      var Tables = new Dictionary<String,List<Dictionary<String,Object>>>(){{"%RasporNum%",EL}};
      Export.export("xlsx",Template,FileName,Poles,Tables, task);
      return true;
    }
    void _ExportListXMLXPilot_Task(Object Param, TaskManager.Task task) {ExportListXMLXPilot((String)Param,task);}
    public TaskManager.Task ExportListXMLXPilot_Task(String FileName){ return m_engine.taskManager.addTask(_ExportListXMLXPilot_Task,"Формирование формы пилотного проекта ", FileName);}
    public class KontInfo
    {
      public Kont kont=null;
      public RegionDate PlanCheck=new RegionDate();//Дата последний плановой проверки
      public Boolean NalogInfo=false;
      public String NalogStatus="";// Статус в налоговой
      public String NalogOKOPF="";
      public RegionDate NalogRegDate=new RegionDate();
      public RegionDate NalogKillDate=new RegionDate();
      public String NalogKontNameFirm="";
      public Dictionary<String,Int32> Okved = new Dictionary<String, Int32>();
      public Dictionary<Int32,Int32> otdels = new Dictionary<Int32, Int32>();
      public String NalogOkvedMain = "";
      public List<String> NalogOkved = new List<String>();
      public List<Raspor> raspors = new List<Raspor>();
      public Dictionary<Int32,Kont.KontObject> objects = new Dictionary<Int32,Kont.KontObject>();
      public List<Def> defs = new List<Def>();
      public Int32 OtdelID=0;
      public Int32 NumPlan=0;
      public Int32 NumVP=0;
      public Int32 NumDef=0;
    }
    void getInfoNalog(KontInfo ki,SqlConnection NalogDB)
    {
      getInfoNalog(ki,NalogDB,ki.kont.OGRN);
    }
    public static void getInfoNalog(KontInfo ki,SqlConnection NalogDB,String OGRN)
    {
      if (!ki.NalogInfo)
      {
         SQLResult resUL = Engine.SQLSelect( @"
SELECT [UL_OPF].[NAME] AS [OKOPF],
  [NAMES],
  [UL_START].[DTREG] AS [DTSTART],
  [UL_FINISH].[DTREG] AS [DTFINISH]
FROM [UL_UL]
  INNER JOIN [UL_NAME] ON [UL_NAME].[IDUL]=[UL_UL].[IDUL]
  INNER JOIN [UL_OPF] ON [UL_OPF].[IDOPF]=UL_NAME.[IDOPF]
  INNER JOIN [UL_START] ON [UL_START].[IDUL]=[UL_UL].[IDUL]
  LEFT JOIN [UL_FINISH] ON [UL_FINISH].[IDUL]=[UL_UL].[IDUL]
WHERE [UL_UL].[OGRN]=@OGRN
",new SQLParam(){{"@OGRN", OGRN}},NalogDB);
        if (resUL.Count>0)
        {
          ki.NalogOKOPF = (String)resUL[0]["OKOPF"];
          ki.NalogKontNameFirm = (String)resUL[0]["NAMES"];
          ki.NalogRegDate = (RegionDate)resUL[0]["DTSTART"];
          ki.NalogKillDate = (RegionDate)resUL[0]["DTFINISH"];
        }
         SQLResult resIP = Engine.SQLSelect( @"
SELECT [FL_MNS].[DTSTART],[FL_MNS].[DTEND],[FAM_FL],[NAME_FL],[OTCH_FL]
FROM [FL_IP]
  INNER JOIN [FL_FL] ON [FL_FL].[IDFL]=[FL_IP].[IDFL]
  INNER JOIN [FL_MNS] ON [FL_MNS].[IDIP]=[FL_FL].[IDIP]
WHERE [FL_IP].[OGRNIP]=@OGRN
",new SQLParam(){{"@OGRN", OGRN}},NalogDB);
        if (resIP.Count>0)
        {
          ki.NalogOKOPF = "Индивидуальный предприниматель";
          String Name = (String)resIP[0]["NAME_FL"];
          String OTCH = (String)resIP[0]["OTCH_FL"];
          ki.NalogKontNameFirm = "ИП "+(String)resIP[0]["FAM_FL"]+" ";
          if (Name.Length>0) ki.NalogKontNameFirm += Name[0]+".";
          if (OTCH.Length>0) ki.NalogKontNameFirm += OTCH[0]+".";
          ki.NalogKontNameFirm=ki.NalogKontNameFirm.Trim();
          ki.NalogRegDate = (RegionDate)resIP[0]["DTSTART"];
          ki.NalogKillDate = (RegionDate)resIP[0]["DTEND"];
        }            
        SQLResult resOkved = Engine.SQLSelect( @"
SELECT [KOD_OKVED],[MAIN]
FROM [UL_UL]
INNER JOIN [UL_OKVED] ON [UL_OKVED].[IDUL]=[UL_UL].[IDUL]
WHERE [UL_UL].[OGRN]=@OGRN
",new SQLParam(){{"@OGRN", OGRN}},NalogDB);
        for(Int32 i=0;i<resOkved.Count;i++)
        {
          if ((String)resOkved[i]["KOD_OKVED"]=="1")
            ki.NalogOkvedMain = (String)resOkved[i]["KOD_OKVED"];
          else
            ki.NalogOkved.Add((String)resOkved[i]["KOD_OKVED"]);
        }        
SQLResult resOkvedIP = Engine.SQLSelect( @"
SELECT [KOD_OKVED],[MAIN]
FROM [FL_IP]
INNER JOIN [FL_OKVED] ON [FL_OKVED].[IDIP]=[FL_IP].[IDIP]
WHERE [FL_IP].[OGRNIP]=@OGRN
",new SQLParam(){{"@OGRN", OGRN}},NalogDB);
        for(Int32 i=0;i<resOkvedIP.Count;i++)
        {
          if ((String)resOkvedIP[i]["KOD_OKVED"]=="1")
            ki.NalogOkvedMain = (String)resOkvedIP[i]["KOD_OKVED"];
          else
            ki.NalogOkved.Add((String)resOkvedIP[i]["KOD_OKVED"]);
        }        
        ki.NalogInfo=true;
      }
    }    
    public bool ExportListXMLXPilot(String FileName, TaskManager.Task task = null)
    {
      MySqlConnection RegionDB = null;
      SqlConnection NalogDB = null;
      var KontInfo = new Dictionary<Int32,KontInfo>();
      var EL = new List<Dictionary<String,Object>>();
      var EL2 = new List<Dictionary<String,Object>>();
      
      Dictionary<Int32,Engine.TOkvedInfo> oi =  m_engine.Okved;
      Dictionary<Int32,Otdel> ot = m_engine.Otdels;
      Dictionary<Int32,String> raions = m_engine.Raions;
      Dictionary<Int32,Engine.DirectInfo> directs = new Dictionary<Int32,Engine.DirectInfo>();
      foreach(var d in m_engine.getDirects())
        directs[d.Value.KontObjectDirect] = d.Value;      
      try
      {
        RegionDB =  m_engine.getRegionDatabase();
        NalogDB = new SqlConnection(m_engine.config.getValue<String>("EGRIPBD",""));
        NalogDB.Open();
        
        var rasporlist = new RasporList(m_engine);
        var deflist = new DefList(m_engine);
        //*
        rasporlist.setWhere("AktDateStart",new RegionDate(2010,1,1,0,0,0,0));
        rasporlist.setWhere("AktDateEnd",new RegionDate(2016,1,1,0,0,0,0));
        /*/
        rasporlist.setWhere("AktDateStart",new RegionDate(2014,1,1,0,0,0,0));
        rasporlist.setWhere("AktDateEnd",new RegionDate(2014,2,1,0,0,0,0));
        /*/
        
        deflist.setWhere("StartStart",new RegionDate(2010,1,1,0,0,0,0));
        deflist.setWhere("StartEnd",new RegionDate(2015,1,1,0,0,0,0));
        /*/        
        deflist.setWhere("StartStart",new RegionDate(2014,1,1,0,0,0,0));
        deflist.setWhere("StartEnd",new RegionDate(2014,2,1,0,0,0,0));
        /**/
        rasporlist.Filter();
        deflist.Filter();
        // Просмотреть все проверки
        if (task!=null)
        {
        	task.TaskName = "Формирование реестра распоряжеиний";
        	task.TaskMax = rasporlist.NumLines;
        	task.TaskValue = 0;
        }
        for(Int32 l=0;l<rasporlist.NumLines;l++)
        {
          RasporListLine line = rasporlist.getLine(l);
          Raspor r = m_engine.getRaspor(line.RasporID);
          r.read(RegionDB);          
            
          if (!KontInfo.ContainsKey(r.KontID))
            KontInfo[r.KontID] = new KontInfo();          
          if (KontInfo[r.KontID].kont==null)
          {
            KontInfo[r.KontID].kont = m_engine.getKont(r.KontID);            
            KontInfo[r.KontID].kont.read(RegionDB);
          }          
          if (r.CheckPlan)
          {
            KontInfo[r.KontID].NumPlan+=1;
            if (KontInfo[r.KontID].PlanCheck==null)
            {
              KontInfo[r.KontID].PlanCheck = r.AktDate;
              KontInfo[r.KontID].OtdelID = r.Otdel.OtdelID;              
            }
            else
            {
              if (KontInfo[r.KontID].PlanCheck.Date < r.AktDate.Date)
              {
                KontInfo[r.KontID].PlanCheck = r.AktDate;
                KontInfo[r.KontID].OtdelID = r.Otdel.OtdelID;
              }
            }
          }
          else
          {
            KontInfo[r.KontID].NumVP+=1;
          }
          String Okved = oi[r.OkvedID].OkvedName;
          if (Okved!="" && Okved!="ОКВЭД")
          {
            if (!KontInfo[r.KontID].Okved.ContainsKey(Okved))
              KontInfo[r.KontID].Okved[Okved]=0;
            KontInfo[r.KontID].Okved[Okved]=KontInfo[r.KontID].Okved[Okved]+1;
          }
          Int32 OtdelID = r.OtdelID;
          if (!KontInfo[r.KontID].otdels.ContainsKey(OtdelID))
              KontInfo[r.KontID].otdels[OtdelID]=0;
          KontInfo[r.KontID].otdels[OtdelID]=KontInfo[r.KontID].otdels[OtdelID]+1;
          foreach(var ro in r.RasporObjects)
            if (r.Kont.KontObjects.ContainsKey(ro.Value.KontObjectID))
              KontInfo[r.KontID].objects[ro.Value.KontObjectID] = r.Kont.KontObjects[ro.Value.KontObjectID];
          KontInfo[r.KontID].raspors.Add(r);
          // Чтение данных из налоговой базы ЮЛ
          
          if (task!=null) task.TaskValue += 1;
        }
        // Просмотреть все административные расследования
        if (task!=null)
        {
        	task.TaskName = "Формирование реестра административных расследований";
        	task.TaskMax = deflist.NumLines;
        	task.TaskValue = 0;
        }
        for(Int32 l=0;l<deflist.NumLines;l++)
        {
          DefListLine line = deflist.getLine(l);
          Def d = m_engine.getDef(line.DefID);
          d.read(RegionDB);          
          if (d.KontID!=0)
          {
            if (!KontInfo.ContainsKey(d.KontID))
              KontInfo[d.KontID] = new KontInfo();          
            
            if (KontInfo[d.KontID].kont==null)
            {
              KontInfo[d.KontID].kont = m_engine.getKont(d.KontID);            
              KontInfo[d.KontID].kont.read(RegionDB);
            }
            KontInfo[d.KontID].NumDef+=1;
            KontInfo[d.KontID].defs.Add(d);
    
            
            Int32 OtdelID = d.OtdelID;
            if (!KontInfo[d.KontID].otdels.ContainsKey(OtdelID))
                KontInfo[d.KontID].otdels[OtdelID]=0;
            KontInfo[d.KontID].otdels[OtdelID]=KontInfo[d.KontID].otdels[OtdelID]+1;
            if (d.Kont.KontObjects.ContainsKey(d.KontObjectID))
              KontInfo[d.KontID].objects[d.KontObjectID] = d.Kont.KontObjects[d.KontObjectID];
          }
          // Чтение данных из налоговой базы ЮЛ
          
          if (task!=null) task.TaskValue += 1;
        }
        
        if (task!=null)
        {
        	task.TaskName = "Сбор дополнительных сведений по субъектам";
        	task.TaskMax = KontInfo.Count;
        	task.TaskValue = 0;
        }        
        foreach(var k in KontInfo)
        {
          // Чтение налоговой базы
          getInfoNalog(k.Value,NalogDB);
          // Выбор отдела для субъекта
          if (k.Value.OtdelID==0)          
            k.Value.OtdelID = (from o in k.Value.otdels orderby o.Value descending select o.Key).Take(1).Single();
          if (task!=null) task.TaskValue += 1;
        }
        Int32 Num=0;
        Int32 NumObject=0;
        // Субъекты
        var kil = from ki in KontInfo orderby ot[ot[ki.Value.OtdelID].OID].OtdelName, ot[ki.Value.OtdelID].OtdelName select ki.Key;
        //foreach(var k in KontInfo)
        foreach(var KontID in kil)
        {
          var k = KontInfo[KontID];
          var ExportLine = new Dictionary<String,Object>();
          ExportLine["%RegionN%"] = "27";
          ExportLine["%Num%"] = Num++;
          ExportLine["%OKOPF%"] = k.NalogOKOPF;
          ExportLine["%KontName%"] = k.kont.KontName;
          ExportLine["%KontNameFirm%"] = k.NalogKontNameFirm;

          ExportLine["%Otdel%"] = ot[k.OtdelID].OtdelName;
          ExportLine["%TO%"] = ot[ot[k.OtdelID].OID].OtdelName;

          var Olist = (from o in k.Okved orderby o.Value descending select o.Key).ToList();
          ExportLine["%Okved%"] = Olist.Count>0?Olist[0]:"";

          //ExportLine["%Okved%"] = k.NalogOkvedMain;
          ExportLine["%OkvedExt%"] = String.Join(", ",k.NalogOkved.ToArray());
          ExportLine["%Region%"] = k.kont.KontRegion;
          ExportLine["%Raion%"] = Region.Engine.getAddressString("","",k.kont.KontRaion,k.kont.KontGorod,"","","","","");
          ExportLine["%Nasp%"] = Region.Engine.getAddressString(k.kont.KontPostIndex,"","",k.kont.KontGorod,k.kont.KontNaspunkt,"","","","");
          ExportLine["%Address%"] = Region.Engine.getAddressString("","","","","",k.kont.KontStreet,k.kont.KontDom,k.kont.KontKorpus,k.kont.KontKvart);
          ExportLine["%INN%"] = k.kont.INN;
          ExportLine["%OGRN%"] = k.kont.OGRN;
          ExportLine["%RegDate%"] = k.NalogRegDate;
          ExportLine["%KillDate%"] = k.NalogKillDate;
          ExportLine["%CheckPlan%"] = k.PlanCheck;
          ExportLine["%KontStart%"] = k.kont.KontStart;          
          ExportLine["%NumPlan%"] = k.NumPlan;
          ExportLine["%NumVP%"] = k.NumVP;
          ExportLine["%NumDef%"] = k.NumDef;
          EL.Add(ExportLine);
          foreach(var ko in k.objects)
          {
            var ExportLine2 = new Dictionary<String,Object>();
            ExportLine2["%Num%"] = NumObject++;
            ExportLine2["%INN%"] = k.kont.INN;
            ExportLine2["%KontObjectID%"] = ko.Key;
            ExportLine2["%Name%"] = ko.Value.KontObjectName;
            ExportLine2["%OKVED%"] = ko.Value.KontObjectOKVED;                        
            ExportLine2["%Raion%"] = Region.Engine.getAddressString("","",raions[ko.Value.KontObjectRaionID],ko.Value.KontObjectGorod,"","","","","");
            ExportLine2["%Nasp%"] = Region.Engine.getAddressString(ko.Value.KontObjectPostIndex,"","",ko.Value.KontObjectGorod,ko.Value.KontObjectNaspunkt,"","","","");
            ExportLine2["%Address%"] = Region.Engine.getAddressString("","","","","",ko.Value.KontObjectStreet,ko.Value.KontObjectDom,ko.Value.KontObjectKorpus,ko.Value.KontObjectKvart);
            ExportLine2["%CheckPlan%"] = k.PlanCheck;
            Int32 NumKO = 0;
            Int32 NumKONar = 0;
            foreach(var raspor in k.raspors)
              if (raspor.RasporObjects.ContainsKey(ko.Key))
            {
              NumKO++;
              if (raspor.NNar==0)
                NumKONar++;
            }
            ExportLine2["%NumKO%"] = NumKO;
            ExportLine2["%NumKONar%"] = NumKONar;
            if(directs.ContainsKey(ko.Value.KontObjectDirect))
              ExportLine2["%Direct%"] = directs[ko.Value.KontObjectDirect].DirectName2;
            else
              ExportLine2["%Direct%"] = "";
            ExportLine2["%Otdel%"] = ot[k.OtdelID].OtdelName;
            ExportLine2["%TO%"] = ot[ot[k.OtdelID].OID].OtdelName;

            EL2.Add(ExportLine2);
          }
          
        }
      }
      finally
      {
        if (RegionDB!=null) 
          RegionDB.Close();
        if (NalogDB!=null)
          NalogDB.Close();
      }
      var Template = m_engine.getRegionFile("Pilot","xlsx");
      var Poles = new Dictionary<String,Object>();
      var Tables = new Dictionary<String,List<Dictionary<String,Object>>>(){{"%RegionN%",EL},{"%Num%",EL2}};
      Export.export("xlsx",Template,FileName,Poles,Tables, task);
      
      return true;
      /*
      var EL = new List<Dictionary<String,Object>>();
      var Raions = m_engine.Raions;
      var KT = m_engine.KontType;
      var Osnov = m_engine.Osnov;
      var Otdels = m_engine.Otdels;
      setWhere("IgnorePage", true);
      var old_lines = new List<RasporListLine>(m_lines);
      if (task!=null) task.TaskName = "Чтение из базы данных";
      Filter();
      var YNN_List = new Dictionary<Int32,String>(){{0,"Нет"},{1,"Да"},{-1,"[Не указан]"}};
      var NNar_List = new Dictionary<Int32,String>(){{0,"Выявлены"},{1,"Не выявлены"},{-1,"[Не указано]"}};
      if (task!=null)
      {
      	task.TaskName = "Формирование реестра распоряжеиний";
      	task.TaskMax = m_lines.Count;
      	task.TaskValue = 0;
      }
      var lawst =  m_engine.LawSt;
      var lawstpoles =  lawst.Keys.ToArray();
      var OkvedList = m_engine.Okved;
      foreach(RasporListLine line in m_lines)
      {
        var ExportLine = new Dictionary<String,Object>();
        var Raspor = m_engine.getRaspor(line.RasporID);        
        for(Int32 i=0;i<lawstpoles.Length;i++)
        {
          ExportLine["%"+lawstpoles[i]+"%"] = 0;
          ExportLine["%"+lawst[lawstpoles[i]].LawID+"%"] = 0;
        }
        foreach(var LawSt in Raspor.LawStNum)
        {
          ExportLine["%"+LawSt.Key+"%"] = LawSt.Value;
          ExportLine["%"+lawst[LawSt.Key].LawID+"%"] = (int)ExportLine["%"+lawst[LawSt.Key].LawID+"%"] + LawSt.Value;
        }
        ExportLine["%Okved%"] = OkvedList[Raspor.OkvedID].OkvedName;
        ExportLine["%RasporNum%"] = Raspor.RasporNum;
        ExportLine["%Date%"] = Raspor.Date;
        ExportLine["%CheckDoc%"] = Raspor.CheckDoc?"Документарная":"";
        ExportLine["%CheckGo%"] = Raspor.CheckGo?"Выездная":"";
        ExportLine["%CheckPlan%"] = Raspor.CheckPlan?"Плановая":"Внеплановая";
        ExportLine["%CheckLicen%"] = Raspor.CheckLicen?"По лицензионному контролю":"";
        if (Raspor.KontID>0)
        {
          var Kont = m_engine.getKont(Raspor.KontID);
          ExportLine["%KontName%"] = Kont.KontName;
          ExportLine["%INN%"] = Kont.INN;
          ExportLine["%OGRN%"] = Kont.OGRN;
          ExportLine["%KontType%"] = KT[Kont.KontTypeID];
          ExportLine["%KontULAddress%"] = Kont.KontULAddress;
          ExportLine["%KontFKAddress%"] = Kont.KontFKAddress;
          ExportLine["%KontGosReg%"] = Kont.KontGosReg;
          ExportLine["%ObjectList%"] = "";
          var KontObjecs = Kont.KontObjects;
          foreach(var RasporObject in Raspor.RasporObjects)
            if (KontObjecs.ContainsKey(RasporObject.Value.KontObjectID))
          {                            
            var KontObject = KontObjecs[RasporObject.Value.KontObjectID];
            ExportLine["%ObjectList%"] +=  KontObject.KontObjectName + ", " + Engine.getAddressString(KontObject.KontObjectPostIndex,KontObject.KontObjectRegion,Raions[KontObject.KontObjectRaionID],KontObject.KontObjectGorod,KontObject.KontObjectNaspunkt,KontObject.KontObjectStreet,KontObject.KontObjectDom,KontObject.KontObjectKorpus,KontObject.KontObjectKvart)+"("+m_engine.KontDirect[KontObject.KontObjectDirect]+")"+";\n";
          }   
        }
        ExportLine["%IspInfo%"] = Raspor.IspInfo;
        ExportLine["%ExpertsInfo%"] = Raspor.ExpertsInfo;
        ExportLine["%TargetInfo%"] = Raspor.TargetInfo;
        ExportLine["%TaskInfo%"] = Raspor.TaskInfo;
        
        ExportLine["%TP%"] = Raspor.TP;
        ExportLine["%Start%"] = Raspor.Start;
        ExportLine["%End%"] = Raspor.End;
        ExportLine["%Osnov%"] = Osnov[Raspor.OsnovID];
        ExportLine["%OsnovInfo%"] = Raspor.OsnovInfo;
        ExportLine["%MKontrInfo%"] = Raspor.MKontrInfo;
        ExportLine["%AReglamInfo%"] = Raspor.AReglamInfo;
        ExportLine["%PDocInfo%"] = Raspor.PDocInfo;
        ExportLine["%Status%"] = Raspor.StatusVip?"Выполнено":"Черновик";            
        ExportLine["%IspUser%"] = m_engine.getUser(Raspor.IspUserID).FIO;
        ExportLine["%Otdel%"] = Otdels[Raspor.OtdelID].OtdelName;
        ExportLine["%NachPodpis%"] = Raspor.NachPodpis==0?"":m_engine.getUser(Raspor.NachPodpis).FIO;
        ExportLine["%RucPodpis%"] = Raspor.RucPodpis==0?"":m_engine.getUser(Raspor.RucPodpis).FIO;
        ExportLine["%Procuror%"] = Raspor.Procuror;
        ExportLine["%Del%"] = Raspor.Del;
        //результаты
        ExportLine["%AktDate%"] = Raspor.AktDate;
        ExportLine["%FStart%"] = Raspor.FStart;
        ExportLine["%FEnd%"] = Raspor.FEnd;
        ExportLine["%PredpisDate%"] = Raspor.PredpisDate;
        ExportLine["%ControlDate%"] = Raspor.ControlDate;
        ExportLine["%PredpisFull%"] = YNN_List[Raspor.PredpisFull];
        ExportLine["%PredpisTime%"] = YNN_List[Raspor.PredpisTime];
        ExportLine["%NNar%"] = NNar_List[Raspor.NNar];
        
        ExportLine["%NumNar%"] = Raspor.NumNar;
        ExportLine["%Predstav%"] = YNN_List[Raspor.Predstav];
        ExportLine["%NStop%"] = YNN_List[Raspor.NStop];
        Dictionary<Int32,Protokol> Protokols = Raspor.Protokols;
        Int32 SumP=0, SumP2=0;
        String ListProtokol = "";
        var Article = m_engine.Article;
        foreach(var P in Protokols)
        {
          String Info ="";
          if (P.Value.MeasureID==1) Info += " штраф "+P.Value.SumP.ToString();
          if (P.Value.MeasureID==2) Info += " предупреждение ";
          if (P.Value.MeasureID==6) Info += " прекращено ";
          if (P.Value.MeasureID==0) Info += " не расмотренно ";
          if (P.Value.MeasureID==4 && P.Value.MeasureSudID==0) Info += " не расмотренно судом ";
          if (P.Value.MeasureSudID==4 || P.Value.MeasureSudID==5) Info += " суд:штраф  "+P.Value.SumP.ToString();
          if (P.Value.MeasureSudID==1 ) Info += " суд:предупреждение  ";
          if (P.Value.MeasureSudID==6 || P.Value.MeasureSudID==7) Info += " суд:Приостановление деятельности  ";
          ListProtokol += "№"+P.Value.ProtokolNum + " от " + P.Value.ProtokolReg.ToShortDateString()+ " " + Article[P.Value.ArticleID]+Info+";\n";
          SumP+=P.Value.SumP;
          SumP2+=P.Value.SumP2;
        }
        Int32 RasporUserTime=0;
        String RasporUserTimeList="";
        foreach(var u in Raspor.RasporUsers)
        {
        	RasporUserTimeList += u.Value.User.FIO + " "+  (u.Value.WorkTime/60.0).ToString()+" ч.;\n";
        	RasporUserTime+= u.Value.WorkTime;
        }
        ExportLine["%RasporUserTime%"] = RasporUserTime/60;
        ExportLine["%RasporUserTimeList%"] = RasporUserTimeList;
        ExportLine["%NumProtokol%"] = Protokols.Count;
        ExportLine["%ListProtokol%"] = ListProtokol;
        ExportLine["%ProtokolSumP%"] = SumP;
        ExportLine["%ProtokolSumP2%"] = SumP2;
        ExportLine["%NLic%"] = YNN_List[Raspor.NLic];
        ExportLine["%SLic%"] = YNN_List[Raspor.SLic];
        ExportLine["%SudZ1%"] = Raspor.SudZ1;
        ExportLine["%SudZ2%"] = Raspor.SudZ2;
        ExportLine["%Nar1%"] = YNN_List[Raspor.Nar1];
        ExportLine["%Nar2%"] = YNN_List[Raspor.Nar2];
        ExportLine["%Nar3%"] = YNN_List[Raspor.Nar3];
        ExportLine["%SudK1%"] = Raspor.SudK1;
        ExportLine["%SudK2%"] = Raspor.SudK2;
        ExportLine["%SudK3%"] = Raspor.SudK3;
        EL.Add(ExportLine);
        if (task!=null) task.TaskValue += 1;
      }      
      setWhere("IgnorePage", false);
      m_lines=old_lines;
      var Template = m_engine.getRegionFile("ReestrRaspor","xlsx");
      var Poles = new Dictionary<String,Object>();
      var Tables = new Dictionary<String,List<Dictionary<String,Object>>>(){{"%RasporNum%",EL}};
      Export.export("xlsx",Template,FileName,Poles,Tables, task);*/
      return true;
    }
    //Кеш списка отделов
    Dictionary<Int32, Dictionary<Int32, String>> m_IspUserList = new Dictionary<Int32, Dictionary<Int32, String>>();
    /// <summary>Возвращает список исполнителей у которых есть хотяб одно распоряжение</summary>
    /// <param name="ParentOtdelID">Отдел</param>        
    public Dictionary<Int32,String> IspUserList( Int32 ParentOtdelID)
    {
      if (m_IspUserList.ContainsKey(ParentOtdelID)) return m_IspUserList[ParentOtdelID];
      var FIO = new List<String>();
      var ID = new List<Int32>();
      Dictionary<Int32,String> R = new Dictionary<int,string>();
      SQLResult r = m_engine.SQLSelect(@"
SELECT raspor.IspUserID, FIO 
FROM raspor 
LEFT JOIN users ON users.UserID = raspor.IspUserID 
INNER JOIN otdel_otdel ON otdel_otdel.OtdelID=raspor.OtdelID
WHERE  otdel_otdel.ParentOtdelID=@ParentOtdelID
GROUP BY raspor.IspUserID", new SQLParam() { { "@ParentOtdelID", ParentOtdelID } });
      for (int i = 0; i < r.Count; i++) R[(Int32)r[i]["IspUserID"]] = (String)r[i]["FIO"];
      m_IspUserList[ParentOtdelID] = R;
      return R;
    }
    Dictionary<Int32, Dictionary<Int32, String>> m_RasporUserList = new Dictionary<Int32, Dictionary<Int32, String>>();
    /// <summary>Возвращает список исполнителей у которых есть хотяб одно распоряжение</summary>
    /// <param name="ParentOtdelID">Отдел</param>        
    public Dictionary<Int32,String> RasporUserList( Int32 ParentOtdelID)
    {
      if (m_RasporUserList.ContainsKey(ParentOtdelID)) return m_RasporUserList[ParentOtdelID];
      var FIO = new List<String>();
      var ID = new List<Int32>();
      Dictionary<Int32,String> R = new Dictionary<int,string>();
      SQLResult r = m_engine.SQLSelect(@"
SELECT users.UserID, FIO 
FROM raspor
INNER JOIN users ON users.UserID = raspor.IspUserID
INNER JOIN rasporuser ON rasporuser.RasporID = raspor.RasporID 
INNER JOIN otdel_otdel ON otdel_otdel.OtdelID=raspor.OtdelID
WHERE  otdel_otdel.ParentOtdelID=@ParentOtdelID
GROUP BY rasporuser.UserID", new SQLParam() { { "@ParentOtdelID", ParentOtdelID } });
      for (int i = 0; i < r.Count; i++) R[(Int32)r[i]["UserID"]] = (String)r[i]["FIO"];
      m_RasporUserList[ParentOtdelID] = R;
      return R;
    }
    /// <summary>Возмращает минимальный и максимальный год выписки распоряжений</summary>
    /// <param name="MinYear"></param><param name="MaxYear"></param>
    public void MinMaxRasporYear(out Int32 MinYear, out Int32 MaxYear)
    {
      SQLResult r = m_engine.SQLSelect("SELECT MIN(RasporYear) AS MinYear, MAX(RasporYear) AS MaxYear FROM raspor WHERE 1");
      if (r.Count == 1)
      {
        MinYear = (Int32)r[0]["MinYear"];
        MaxYear = (Int32)r[0]["MaxYear"];
      }
      else
      {
        MinYear = DateTime.Now.Year;
        MaxYear = DateTime.Now.Year;
      }
    }
    public RasporList(Engine engine):base(engine)
    {
      DefaultPoles.Add("raspor.RasporID");
      DefaultPoles.Add("raspor.OnlineID");
      DefaultPoles.Add("raspor.RucPodpis");
      DefaultPoles.Add("raspor.RasporNum");
      DefaultPoles.Add("raspor.Date");
      DefaultPoles.Add("raspor.StatusVip");
      DefaultPoles.Add("kont.KontName");
      DefaultPoles.Add("isp.FIO AS IspFIO");
      DefaultTables.Add("raspor");
      DefaultTables.Add("LEFT JOIN kont ON kont.KontID=raspor.KontID");
      DefaultTables.Add("LEFT JOIN users AS isp ON isp.UserID=raspor.IspUserID");
      DefaultOrderBy.Add("raspor.RasporNum DESC");
    }
    protected override void ProceessWheres(SQLParam Params,List<String> Tables, List<String> Poles,List<String> Wheres,List<String> OrderBy)
    {

      Int32 RasporID, ParentOtdelID, RasporYear, RasporNumStart, RasporNumEnd, IspUserID,RasporUserID, LineInPage, Page, CheckPlan;
      if (m_wheres.ContainsKey("Mode"))
      {
          if ((String)m_wheres["Mode"] == "Raspor")
          {
              Poles.Clear();
              Poles.Add("raspor.*");              
          }
          else if ((String)m_wheres["Mode"] == "RasporObject")
          {
              Poles.Clear();
              Poles.Add("ro.*");
              Tables.Add("INNER JOIN rasporobject AS ro ON ro.RasporID=raspor.RasporID");                          
          }
          else if ((String)m_wheres["Mode"] == "RasporUser")
          {
              Poles.Clear();
              Poles.Add("ru.*");
              Tables.Add("INNER JOIN rasporuser AS ru ON ru.RasporID=raspor.RasporID");
          }
      }
      if (m_wheres.ContainsKey("Sort"))
      {
          OrderBy.Clear();
          foreach(String s in ((String)m_wheres["Sort"]).Split(','))          
              OrderBy.Add(s.Trim());
          
      }
      if (m_wheres.ContainsKey("NoPodpis") && (bool)m_wheres["NoPodpis"])
      {
        Wheres.Add("raspor.RucPodpis=0");               
      }
      if (m_wheres.ContainsKey("Podpis") && (bool)m_wheres["Podpis"])
      {
        Wheres.Add("raspor.RucPodpis<>0");               
      }
      if (m_wheres.ContainsKey("CheckPlan") && Int32.TryParse(m_wheres["CheckPlan"].ToString(), out CheckPlan))
      {
        Wheres.Add("raspor.CheckPlan=@CheckPlan");
        Params["@CheckPlan"] = CheckPlan;
      }
      foreach(String Pole in new String[]{"Date", "AktDate", "Start", "End", "ControlDate" })
      {            
        if (m_wheres.ContainsKey(Pole + "Start"))
        { 
          var date = m_wheres[Pole + "Start"] as RegionDate;
          if (date==null&& m_wheres[Pole + "Start"] is DateTime)
              date = new RegionDate((DateTime)m_wheres[Pole + "Start"]);
          if (date!=null && !(date.Empty))
          {
            Wheres.Add("raspor." + Pole + " >= @" + Pole + "Start");
            Params["@" + Pole + "Start"] = date.getRegionDate();
          }
        }
        if (m_wheres.ContainsKey(Pole + "End"))
        {
          var date = m_wheres[Pole + "End"] as RegionDate;
          if (date==null&& m_wheres[Pole + "End"] is DateTime)
              date = new RegionDate((DateTime)m_wheres[Pole + "End"]);
          if (date!=null && !(date.Empty))
          {
            Wheres.Add("raspor." + Pole + " < @" + Pole + "End");
            Params["@" + Pole + "End"] = date.getRegionDate();
          }
        }
      }
      if (m_wheres.ContainsKey("RasporID") && m_wheres["RasporID"] != null && Int32.TryParse(m_wheres["RasporID"].ToString(), out RasporID))
      {
        Wheres.Add("raspor.RasporID=@RasporID");
        Params["@RasporID"] = RasporID;
      }
      if (m_wheres.ContainsKey("ParentOtdelID") && m_wheres["ParentOtdelID"] != null && Int32.TryParse(m_wheres["ParentOtdelID"].ToString(), out ParentOtdelID))
      {
        Tables.Add("INNER JOIN otdel_otdel ON otdel_otdel.OtdelID=raspor.OtdelID");
        Wheres.Add("otdel_otdel.ParentOtdelID=@ParentOtdelID");
        Params["@ParentOtdelID"] = ParentOtdelID;
      }
      if (m_wheres.ContainsKey("RasporYear") && m_wheres["RasporYear"] != null && Int32.TryParse(m_wheres["RasporYear"].ToString(), out RasporYear) && RasporYear>0)
      {
        Wheres.Add("raspor.RasporYear=@RasporYear");
        Params["@RasporYear"] = RasporYear;
      }

      if (m_wheres.ContainsKey("RasporNumStart") && m_wheres["RasporNumStart"] != null && Int32.TryParse(m_wheres["RasporNumStart"].ToString(), out RasporNumStart) && RasporNumStart > 0)
      {
        Wheres.Add("raspor.RasporNum>=@RasporNumStart");
        Params["@RasporNumStart"] = RasporNumStart;
      }
      if (m_wheres.ContainsKey("RasporNumEnd") && m_wheres["RasporNumEnd"] != null && Int32.TryParse(m_wheres["RasporNumEnd"].ToString(), out RasporNumEnd) && RasporNumEnd > 0)
      {
        Wheres.Add("raspor.RasporNum<=@RasporNumEnd");
        Params["@RasporNumEnd"] = RasporNumEnd;
      }
      if (m_wheres.ContainsKey("IspUserID") && m_wheres["IspUserID"] != null && Int32.TryParse(m_wheres["IspUserID"].ToString(), out IspUserID) && IspUserID>0)
      {
        Wheres.Add("raspor.IspUserID=@IspUserID");
        Params["@IspUserID"] = IspUserID;
      }
      if (m_wheres.ContainsKey("RasporUserID") && m_wheres["RasporUserID"] != null && Int32.TryParse(m_wheres["RasporUserID"].ToString(), out RasporUserID) && RasporUserID>0)
      {
        Tables.Add("INNER JOIN rasporuser ON rasporuser.RasporID=raspor.RasporID");
        Wheres.Add("rasporuser.UserID=@RasporUserID");
        Params["@RasporUserID"] = RasporUserID;
      }
      if (m_wheres.ContainsKey("Find") && m_wheres["Find"] != null)
      {
          Wheres.Add("MATCH(KontName,KontGorod,KontNaspunkt,KontStreet,KontFGorod,KontFNaspunkt,KontFStreet,INN,OGRN) AGAINST (@Find1 IN BOOLEAN MODE)");
          OrderBy.Insert(0, "MATCH(KontName,KontGorod,KontNaspunkt,KontStreet,KontFGorod,KontFNaspunkt,KontFStreet,INN,OGRN) AGAINST (@Find2) DESC");
          Params["@Find1"] = (String)m_wheres["Find"];
          Params["@Find2"] = (String)m_wheres["Find"];
      }
      if (m_wheres.ContainsKey("Contain") && m_wheres["Contain"] != null)
      {
          //var poles = new Dictionary<String, Int32> { { "KontName", 3 }, { "KontGorod", 1 }, { "KontNaspunkt", 1 }, { "KontStreet", 1 }, { "KontFGorod", 1 }, { "KontFNaspunkt", 1 }, { "KontFStreet", 1 }, { "INN", 2 }, { "OGRN", 2 } };
          var poles = new Dictionary<String, Int32> { { "KontName", 3 } };
          Int32 PoleN = 1;
          var W = new List<String>();
          foreach (String Word in ((String)m_wheres["Contain"]).Split(' '))
          {
              String Word2 = Word.Trim();
              if (Word2.Length>=3)
              {
                  Word2 = "%" + Word2 + "%";
                  foreach (var Pole in poles)
                  {
                      W.Add("((" + Pole.Key + " LIKE @Contain" + PoleN.ToString() + ")*" + Pole.Value+")");
                      Params["@Contain" + PoleN.ToString()] = Word2;
                      PoleN++;
                  }
                  
              }
          }
          if (W.Count > 0)
          {
              var Pole = String.Join("+", W.ToArray()) ;
              Poles.Add(Pole + " AS Contain ");
              Wheres.Add(Pole+">0");
              OrderBy.Insert(0, "Contain DESC");
          }
      }        
    }    
    protected override RasporListLine readLine(Dictionary<String, Object> r)
    {
      var l = new RasporListLine();
        l.RasporID = (Int32)r["RasporID"];
        l.RasporNum = (Int32)r["RasporNum"];
        l.OnlineID = (Int32)r["OnlineID"];
        try { l.KontName = Engine.RegionStringToString((String)r["KontName"]); }
        catch { l.KontName = ""; }
        try { l.IspFIO = Engine.RegionStringToString((String)r["IspFIO"]); }
        catch { l.IspFIO = ""; }
        l.Date = Engine.IntToRegionDate((Int32)r["Date"]);
        l.Podpis = ((Int32)r["RucPodpis"] > 0);
        l.StatusVip = (Boolean)r["StatusVip"];
      return l;
    }
    protected override Boolean preLoadObject<T>(Dictionary<String, Object> Fields, Object PkValue)
    {
        m_engine.getRaspor((Int32)PkValue, Fields);
        return true;
    }
    public override Boolean preLoad<T>(Dictionary<Int32, Dictionary<String, Object>> Fields = null)     
    {
        if (Fields == null)
        {                        
            var RasporFields = preLoadFields<T>();
            setWhere("Mode", "RasporObject");            
            var RU = new Dictionary<Int32, Dictionary<Int32, Dictionary<String, Object>>>();//RasporID.N.PoleName
            foreach (var i in preLoadFields<T>())
            {
                Int32 RasporID = (Int32)i.Value["RasporID"];
                if(!RU.ContainsKey(RasporID))
                    RU[RasporID] = new Dictionary<Int32, Dictionary<String, Object>>();
                RU[RasporID][RU[RasporID].Count] = i.Value;
            }
            setWhere("Mode", "RasporUser");
            var RO = new Dictionary<Int32, Dictionary<Int32, Dictionary<String, Object>>>();//RasporID.N.PoleName
            foreach (var i in preLoadFields<T>())
            {
                Int32 RasporID = (Int32)i.Value["RasporID"];
                if (!RO.ContainsKey(RasporID))
                    RO[RasporID] = new Dictionary<Int32, Dictionary<String, Object>>();
                RO[RasporID][RO[RasporID].Count] = i.Value;
            }
            foreach (var i in RasporFields)
            {
                Int32 RasporID = (Int32)i.Value["RasporID"];
                i.Value["RasporObject"] = RO.ContainsKey(RasporID)?RO[RasporID]:new Dictionary<Int32, Dictionary<String, Object>>();
                i.Value["RasporUser"] = RU.ContainsKey(RasporID)?RU[RasporID]:new Dictionary<Int32, Dictionary<String, Object>>();
            }
            Fields = RasporFields;            
        }
        return base.preLoad<T>(Fields);
    }
  }
  public partial class Engine
  {
      /// <summary> Список открытых распояжений </summary>
      private Dictionary<Int32, Raspor> l_Raspor;
      /// <summary> Загружает данные распоряжений одним запросом</summary>
      /// <param name="Wheres">смотри UserList.ProceessWheres</param>
      /// <returns>Если пред загрузка удалаяь true</returns>
      public Boolean preLoadRaspor(IDictionary<String, Object> Wheres)
      {
          return preLoadRaspor(null, Wheres);
      }
      public Boolean preLoadRaspor(RasporList list = null, IDictionary<String, Object> Wheres = null)
      {
          if (list == null)
              list = new RasporList(this);
          Object oldMode = list.getWhere("Mode");
          list.setWhere("Mode", "Raspor");
          if (Wheres != null)
              foreach (var w in Wheres)
                  list.setWhere(w.Key, w.Value);
          Boolean result =  list.preLoad<Raspor>();
          list.setWhere("Mode", oldMode);
          return result;
      }
      /// <summary> Получить распоряжение по его идентификатору</summary><param name="RasporID">ИД Распоряжения</param><returns>Объект распоряжения</returns>
      public Raspor getRaspor(Int32 RasporID, IDictionary<String, Object> Fields = null)
      {
        if (l_Raspor == null) l_Raspor = new Dictionary<Int32, Raspor>();
        if (l_Raspor.ContainsKey(RasporID)) return (Raspor)l_Raspor[RasporID];
        var raspor = new Raspor(this, RasporID, Fields);
        l_Raspor[RasporID] = raspor;
        return raspor;
      }

      /// <summary>Создать новое распоряжение</summary><param name="BaseRasporID">Идентификатор распоряжения на основе которого создаётся распоряжение</param><returns>Идентификатор нового расоряжения</returns>
      public Int32 newRaspor(Int32 BaseRasporID)
      {
        
        var Param = new SQLParam();
        Param["@RasporYear"] = DateTime.Now.Year;
        Param["@Date"] = RegionDateToInt(DateTime.Now);
        Param["@IspUserID"] = CurrentUser.UserID;
        Param["@OtdelID"] = CurrentUser.OtdelID;
        var Poles = new String[] { "CheckPlan", "CheckDoc", "CheckGo", "ExpertsInfo", "TargetInfo", "TaskInfo", "Pred", "TP", "OsnovID", "MKontrInfo", "AReglamInfo", "PDocInfo", "OsnovInfo" };
        var SqlPoles = new String[0];
        String SqlPolesN = "";
        //foreach (String Pole in Poles) Param["@" + Pole] = "";

        if (BaseRasporID > 0)
        {
          Raspor raspor = getRaspor(BaseRasporID);
          SqlPoles = Poles;
          IDictionary<String, Object> rPoles = raspor.getPoles();
          foreach (String Pole in Poles)
          {
              Param["@" + Pole] = rPoles[Pole];
            SqlPolesN += ", @" + Pole + " AS " + Pole;
          }
        }
        MySqlCommand cmd;
        SQLEdit(@"
INSERT INTO raspor(RasporNum,RasporYear,Date,IspUserID,OtdelID " + ((SqlPoles.Length > 0) ? ", " : "") + String.Join(" ,", SqlPoles) + @") 
SELECT R1.RasporNum+1 AS RasporNum, @RasporYear AS RasporYear, @Date AS Date, 
@IspUserID AS IspUserID, @OtdelID AS OtdelID " + SqlPolesN + @"
FROM raspor AS R1 
LEFT JOIN raspor AS R2 ON (R2.RasporNum=R1.RasporNum+1 AND R2.RasporYear=@RasporYear ) 
WHERE R2.RasporNum IS NULL AND R1.RasporYear=@RasporYear 
ORDER BY R1.RasporNum 
LIMIT 1", Param, out cmd);
        return (Int32)cmd.LastInsertedId;
      }
      /// <summary>Удалить распоряжение</summary><param name="RasporID">ИД распоряжения</param><returns>true - если распоряжение было удалено</returns>
      public bool delRaspor(Int32 RasporID)
      {
        Raspor raspor = getRaspor(RasporID);
        if (!CurrentUser.isAccess("EditRaspor")) return false;// Пользователь неимеет права удалять распоряжения            
        if (!CurrentUser.isAccess("Admin") && CurrentUser.OtdelID != raspor.OtdelID && !Otdels[CurrentUser.OtdelID].isSubOtdel(raspor.OtdelID)) return false;//нельзя удалить черновик другово отдела
        var Param = new SQLParam();
        Param["RasporID"] = RasporID;
        //Удалить само распоряжение
        Int32 N = SQLEdit("DELETE FROM raspor WHERE RasporID=@RasporID AND RucPodpis=0 AND NachPodpis=0 AND StatusVip=0", Param);
        if (N == 1) // Распоряжение действительно удалено. 
        {
          l_Raspor.Remove(RasporID);
          //Удалить выбранные объекты
          SQLEdit("DELETE FROM rasporobject WHERE RasporID=@RasporID", Param);
          //Удалить проверяющих из проверки
          SQLEdit("DELETE FROM rasporuser WHERE RasporID=@RasporID", Param);
          return true;
        }
        return false;
      }

  }
  
}